package com.aos.erp.message.service.impl;

import com.aos.common.Constants;
import com.aos.erp.common.bean.IPageBean;
import com.aos.erp.common.bean.PageBean;
import com.aos.erp.common.dao.mapper.Condition;
import com.aos.erp.common.exception.BizException;
import com.aos.erp.message.dto.MessageRecordDTO;
import com.aos.erp.message.dto.MessageRecordItemDTO;
import com.aos.erp.message.dto.MessageRecordWaitPushItemDTO;
import com.aos.erp.message.dto.MessageTemplateDTO;
import com.aos.erp.message.enums.DelStatus;
import com.aos.erp.message.enums.PushStatus;
import com.aos.erp.message.enums.PushType;
import com.aos.erp.message.enums.SmsType;
import com.aos.erp.message.mapper.*;
import com.aos.erp.message.model.*;
import com.aos.erp.message.model.vo.MRConditionVo;
import com.aos.erp.message.model.vo.PushMessageVo;
import com.aos.erp.message.model.vo.PushStudentVo;
import com.aos.erp.message.model.vo.SmsMessageVo;
import com.aos.erp.message.service.MessageRecordService;
import com.aos.erp.message.service.MessageTemplateService;
import com.aos.erp.message.task.MessageTaskTrigger;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;

@Slf4j
@Service
public class MessageRecordServiceImpl extends ServiceImpl<MessageRecordMapper, MessageRecordInfo> implements MessageRecordService {

    @Resource
    private MRContentAppMapper contentAppMapper;
    @Resource
    private MRContentSmsMapper contentSmsMapper;
    @Resource
    private MRContentWxPublicMapper contentWxPublicMapper;
    @Resource
    private MRContentWxAppletMapper contentWxAppletMapper;
    @Resource
    private MRWaitPushMapper waitPushMapper;
    @Resource
    private MessageTemplateService messageTemplateService;

    @Resource
    private MessageTaskTrigger messageTaskTrigger;

    @Value("${spring.application.name}")
    private String appName;
    /**
     * 保存消息记录
     * @param dataInfo
     * @throws BizException
     */
    @Override
    public void saveRecord(PushMessageVo dataInfo) throws BizException {

        // 校验数据
        checkSaveRecordData(dataInfo);

        // 获取模板信息
        MessageTemplateDTO messageTemplateDTO = messageTemplateService.getTemplateDetail(dataInfo.getMtId());

        // 遍历学员列表，向每个学员推送信息
        for (PushStudentVo studentItem : dataInfo.getPushStudentList()) {
            pushMessageToStudent(messageTemplateDTO, dataInfo, studentItem);
        }
    }

    /**
     * 向学员推送消息
     */
    private void pushMessageToStudent(MessageTemplateDTO messageTemplateDTO, PushMessageVo dataInfo, PushStudentVo studentItem) {
        // 根据推送类型，保存推送消息记录
        for (PushType pushType : messageTemplateDTO.getPushTypeList()) {
            // 保存消息记录，获得消息记录ID
            MessageRecordInfo messageRecordInfo = saveMessageRecord(dataInfo, studentItem, messageTemplateDTO, pushType);

            // 保存待发消息记录
            saveWaitMessageRecord(messageRecordInfo);

            // 根据推送方式，保存推送内容
            if(pushType == PushType.app) {
                // APP 推送
                saveContentApp(messageRecordInfo.getId(), dataInfo);
            } else if(pushType == PushType.wx_public) {
                // 公众号推送
                saveContentWxPublic(messageRecordInfo.getId(), messageTemplateDTO);
            } else if(pushType == PushType.wx_applet) {
                // 小程序推送
                saveContentWxApplet(messageRecordInfo.getId(), dataInfo, messageTemplateDTO);
            } else if(pushType == PushType.sms) {
                // 短信 推送
                saveContentSms(messageRecordInfo.getId(), messageTemplateDTO);
            }
        }
    }

    /**
     * 保存消息记录
     * @param dataInfo
     * @throws BizException
     */
    @Override
    public void saveSmsRecord(SmsMessageVo dataInfo) throws BizException {

        // 校验数据
        checkSaveSmsRecordData(dataInfo);

        // 保存消息记录，获得消息记录ID
        Date nowDate = new Date();
        MessageRecordInfo recordInfo = new MessageRecordInfo();
        recordInfo.setIsDel(DelStatus.del_no);
        recordInfo.setMrPushCount(0);
        recordInfo.setMrRecipient(dataInfo.getPhone());
        recordInfo.setMrRecipientPhone(dataInfo.getPhone());
        recordInfo.setMrRecipientIdNo(dataInfo.getPhone());
        recordInfo.setMrDsId(0);
        recordInfo.setMrDsName("平台");
        recordInfo.setMrSenderName("平台");
        recordInfo.setMtId(0);
        recordInfo.setMrTitle("平台及时短信");
        recordInfo.setMtCode("");
        recordInfo.setMrMsgParams(dataInfo.getMsgParams());
        recordInfo.setPushStatus(PushStatus.push_no);
        recordInfo.setPushType(PushType.sms_timely);
        recordInfo.setSubmitTime(nowDate);
        baseMapper.insert(recordInfo);

        // 发送短信
        String smsTemplateId = "";
        if(dataInfo.getSmsType() == SmsType.sms_yzm) {
            smsTemplateId = Constants.SMSTEMPID_YZM_IDNUM_CODE;
        }
        String sendResult = messageTaskTrigger.sendSmsMsg(recordInfo.getMrRecipientPhone(), smsTemplateId, dataInfo.getMsgParams());

        // 消息内容
        MRContentSmsInfo contentInfo = new MRContentSmsInfo();
        contentInfo.setMrId(recordInfo.getId());
        contentInfo.setMrSmsTemplateId(smsTemplateId);
        contentSmsMapper.insert(contentInfo);

        recordInfo.setMrPushCount(recordInfo.getMrPushCount() + 1);
        recordInfo.setPushTime(new Date());
        recordInfo.setPushStatus(PushStatus.push_yes);
        recordInfo.setMrContent(smsTemplateId);
        recordInfo.setPushResult(sendResult);
        baseMapper.updateById(recordInfo);
    }

    /**
     *
     * 修改推送状态
     * @param mrId 记录ID
     * @param pushStatus 推送状态
     * @param pushResult 推送结果
     */
    @Override
    public void updatePushStatus(long mrId, PushStatus pushStatus, String pushResult) {

        MessageRecordInfo recordInfo = baseMapper.selectById(mrId);

        recordInfo.setMrPushCount(recordInfo.getMrPushCount() + 1);
        recordInfo.setPushTime(new Date());
        recordInfo.setPushStatus(pushStatus);
        recordInfo.setPushResult(pushResult);
        baseMapper.updateById(recordInfo);

        if(pushStatus == PushStatus.push_yes) {
            // 推送成功
            waitPushMapper.deleteById(mrId);
        } else {
            waitPushMapper.updatePushCount(mrId);
        }
    }

    /**
     * 获取推送记录详情
     * @param dataId
     * @return
     */
    @Override
    public MessageRecordDTO getRecordDetail(long dataId) {
        MessageRecordDTO messageRecordDTO = new MessageRecordDTO();

        // 获取消息记录信息
        MessageRecordInfo recordInfo = baseMapper.selectById(dataId);
        messageRecordDTO.setMessageRecord(recordInfo);

        // 根据消息推送类型，查询消息内容

        if(recordInfo.getPushType() == PushType.app) {
            // APP 推送
            Condition condition = new Condition(MRContentAppInfo.class);
            condition.eqFiled("mrId", dataId);
            MRContentAppInfo contentAppInfo = contentAppMapper.selectOne(condition.getWrapper());
            messageRecordDTO.setContentAppInfo(contentAppInfo);
        } else if(recordInfo.getPushType() == PushType.wx_public) {
            // 公众号推送
            Condition condition = new Condition(MRContentWxPublicInfo.class);
            condition.eqFiled("mrId", dataId);
            MRContentWxPublicInfo contentPublicInfo = contentWxPublicMapper.selectOne(condition.getWrapper());
            messageRecordDTO.setContentForPublic(contentPublicInfo);
        } else if(recordInfo.getPushType() == PushType.wx_applet) {
            // 小程序推送
            Condition condition = new Condition(MRContentWxAppletInfo.class);
            condition.eqFiled("mrId", dataId);
            MRContentWxAppletInfo contentAppletInfo = contentWxAppletMapper.selectOne(condition.getWrapper());
            messageRecordDTO.setContentForApplet(contentAppletInfo);
        } else if(recordInfo.getPushType() == PushType.sms) {
            // 短信 推送
            Condition condition = new Condition(MRContentSmsInfo.class);
            condition.eqFiled("mrId", dataId);
            MRContentSmsInfo contentSmsInfo= contentSmsMapper.selectOne(condition.getWrapper());
            messageRecordDTO.setContentForSms(contentSmsInfo);
        }
        return messageRecordDTO;
    }

    /**
     * 查询固定条待发消息
     * @param conditionVo
     * @return
     */
    @Override
    public List<MRWaitPushInfo> findWaitSend(MRConditionVo conditionVo) {
        IPageBean<MRWaitPushInfo> page = waitPushMapper.createBizPage(conditionVo.getPageIndex(), conditionVo.getPageSize());

        Condition condition = new Condition(MRWaitPushInfo.class);
        IPageBean pageBean = waitPushMapper.selectPage(page, condition.getWrapper());
        return (List<MRWaitPushInfo>)pageBean.getRecords();
    }

    /**
     * 分页查询待发消息列表
     * @param conditionVo
     * @return
     */
    @Override
    public PageBean<MessageRecordWaitPushItemDTO> findWaitSendByPage(MRConditionVo conditionVo) {
        Page<MessageRecordWaitPushItemDTO> page = new Page<MessageRecordWaitPushItemDTO>(conditionVo.getPageIndex(), conditionVo.getPageSize());
        List<MessageRecordWaitPushItemDTO> noticeInfoList = waitPushMapper.pageRecordList(page, conditionVo);
        page.setRecords(noticeInfoList);

        PageBean<MessageRecordWaitPushItemDTO> bean = new PageBean<MessageRecordWaitPushItemDTO>(page.getCurrent(), page.getSize(), page.getTotal());
        bean.setOptimizeCountSql(page.optimizeCountSql());
        bean.setAscs(page.ascs());
        bean.setDescs(page.descs());
        bean.setRecords(page.getRecords());
        bean.condition();

        return bean;
    }

    /**
     * 分页查询消息记录列表
     * @param conditionVo
     * @return
     */
    @Override
    public PageBean<MessageRecordItemDTO> findByPage(MRConditionVo conditionVo) {
        Page<MessageRecordItemDTO> page = new Page<MessageRecordItemDTO>(conditionVo.getPageIndex(), conditionVo.getPageSize());
        List<MessageRecordItemDTO> noticeInfoList = baseMapper.pageRecordList(page, conditionVo);
        page.setRecords(noticeInfoList);

        PageBean<MessageRecordItemDTO> bean = new PageBean<MessageRecordItemDTO>(page.getCurrent(), page.getSize(), page.getTotal());
        bean.setOptimizeCountSql(page.optimizeCountSql());
        bean.setAscs(page.ascs());
        bean.setDescs(page.descs());
        bean.setRecords(page.getRecords());
        bean.condition();

        return bean;
    }

    @Override
    public void deleteRecord(String dataId) throws BizException {

        if(dataId.isEmpty()) {
            throw new BizException("消息记录ID不能为空");
        }
        baseMapper.deleteRecord(dataId);
    }

    /**
     * 保存APP 消息内容
     * @param mrId
     * @param dataInfo
     */
    private void saveContentApp(long mrId, PushMessageVo dataInfo) {
        MRContentAppInfo contentInfo = new MRContentAppInfo();
        contentInfo.setMrId(mrId);
        contentInfo.setMrBizData(dataInfo.getBizData());
        contentAppMapper.insert(contentInfo);
    }

    /**
     *
     * 保存微信公众号 消息内容
     * @param mrId
     * @param messageTemplateDTO
     */
    private void saveContentWxPublic(long mrId, MessageTemplateDTO messageTemplateDTO) {
        MRContentWxPublicInfo contentInfo = new MRContentWxPublicInfo();
        contentInfo.setMrId(mrId);
        contentInfo.setMrUrl(messageTemplateDTO.getMtUrlForPublic());
        contentInfo.setMrWxTemplateId(messageTemplateDTO.getMtWxTemplateIdForPublic());
        contentWxPublicMapper.insert(contentInfo);
    }

    /**
     *
     * 保存微信小程序 消息内容
     * @param mrId
     * @param dataInfo
     * @param messageTemplateDTO
     */
    private void saveContentWxApplet(long mrId, PushMessageVo dataInfo, MessageTemplateDTO messageTemplateDTO) {
        MRContentWxAppletInfo contentInfo = new MRContentWxAppletInfo();
        contentInfo.setMrId(mrId);
        contentInfo.setMrWxTemplateId(messageTemplateDTO.getMtWxTemplateIdForApplet());
        contentInfo.setMrUrl(messageTemplateDTO.getMtUrlForApplet());
        contentInfo.setMrFormId(dataInfo.getFormId());
        contentWxAppletMapper.insert(contentInfo);
    }

    /**
     * 保存短信 消息内容
     * @param mrId
     * @param messageTemplateDTO
     */
    private void saveContentSms(long mrId, MessageTemplateDTO messageTemplateDTO) {
        MRContentSmsInfo contentInfo = new MRContentSmsInfo();
        contentInfo.setMrId(mrId);
        contentInfo.setMrSmsTemplateId(messageTemplateDTO.getMtSmsTemplateId());
        contentSmsMapper.insert(contentInfo);
    }

    /**
     * 保存消息推送记录
     * @param dataInfo
     * @return
     */
    private MessageRecordInfo saveMessageRecord(PushMessageVo dataInfo, PushStudentVo studentItem, MessageTemplateDTO messageTemplateDTO, PushType pushType) {
        Date nowDate = new Date();
        MessageRecordInfo recordInfo = new MessageRecordInfo();
        recordInfo.setIsDel(DelStatus.del_no);
        recordInfo.setMrPushCount(0);
        recordInfo.setMrRecipient(studentItem.getStudentName());
        recordInfo.setMrRecipientPhone(studentItem.getStudentPhone());
        recordInfo.setMrRecipientIdNo(studentItem.getIdNo());
        recordInfo.setMrDsId(dataInfo.getDsId());
        recordInfo.setMrDsName(dataInfo.getDsName());
        recordInfo.setMrSenderName(dataInfo.getSenderName());
        if(pushType == PushType.app) {
            recordInfo.setMrContent(studentItem.getPushMessageForApp());
            recordInfo.setMrMsgParams(studentItem.getMsgParamsForApp());
        } else if (pushType == PushType.wx_public) {
            recordInfo.setMrContent(studentItem.getPushMessageForPublic());
            recordInfo.setMrMsgParams(studentItem.getMsgParamsForPublic());
        } else if (pushType == PushType.wx_applet) {
            recordInfo.setMrContent(studentItem.getPushMessageForApplet());
            recordInfo.setMrMsgParams(studentItem.getMsgParamsForApplet());
        } else if (pushType == PushType.sms) {
            recordInfo.setMrContent(studentItem.getPushMessageForSms());
            recordInfo.setMrMsgParams(studentItem.getMsgParamsForSms());
        }
        recordInfo.setMtId(dataInfo.getMtId());
        recordInfo.setMrTitle(messageTemplateDTO.getMessageTemplate().getMtTitle());
        recordInfo.setMtCode(messageTemplateDTO.getMessageTemplate().getMtCode());
        recordInfo.setPushStatus(PushStatus.push_no);
        recordInfo.setPushType(pushType);
        recordInfo.setSubmitTime(nowDate);
        this.save(recordInfo);
        return recordInfo;
    }

    /**
     * 保存待发消息推送记录
     * @param dataInfo
     * @return
     */
    private void saveWaitMessageRecord(MessageRecordInfo dataInfo) {
        MRWaitPushInfo waitPushInfo = new MRWaitPushInfo();
        BeanUtils.copyProperties(dataInfo, waitPushInfo);
        waitPushMapper.insert(waitPushInfo);
    }

    private void checkSaveRecordData(PushMessageVo params)  throws BizException {
        if(params.getMtId() == 0) {
            throw new BizException("模板ID不能为空");
        }
        if(params.getPushStudentList().size() == 0) {
            throw new BizException("推送学员不能为空");
        }
        PushStudentVo pushStudentItem = params.getPushStudentList().get(0);
        if(pushStudentItem.getPushMessageForApp().length() == 0
                && pushStudentItem.getPushMessageForPublic().length() == 0
                && pushStudentItem.getPushMessageForApplet().length() == 0
                && pushStudentItem.getPushMessageForSms().length() == 0) {
            throw new BizException("推送消息不能为空");
        }
        if(params.getDsId() == 0) {
            throw new BizException("发送驾校ID不能为空");
        }
        if(params.getDsName().length() == 0) {
            throw new BizException("发送驾校名称不能为空");
        }
        if(params.getSenderName().length() == 0) {
            throw new BizException("发送人名称不能为空");
        }
    }

    private void checkSaveSmsRecordData(SmsMessageVo params)  throws BizException {

        if(params.getPhone().length() == 0) {
            throw new BizException("接收人电话不能为空");
        }
        if(params.getSmsType() == null || params.getSmsType() == SmsType.sms_none) {
            throw new BizException("请指定消息类型");
        }
        if(params.getSmsType() == SmsType.sms_yzm) {
            if(params.getMsgParams().length() == 0) {
                throw new BizException("短信验证码需要缺少参数");
            }
        }
    }
}
